//
// Copyright (c) 2009-2011, chunquedong
//
// This file is part of ChunMap project
// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE(Version >=3)
//
// History:
//   2011-10-29  Jed Young  Creation
//

using concurrent
using gfx
using array
using gfx::Point as FPoint
using gfx2
using fan3dMath
using fan3dMath::Vector as Vector3D

using chunmapModel
using chunmapData

**
** Arrow Symbolizer
**
@Js
const class ArrowSym : GeometrySym
{
  private const Unsafe geometry
  private const Color color
  private const Float dis := 20f

  new make(Color color := Color.black, Int w := 12, Int h := 4)
  {
    this.color = color
    p1 := Coord(-w.toFloat, h.toFloat)
    p2 := Coord(0f, 0f)
    p3 := Coord(-w.toFloat, -h.toFloat)
    geometry = Unsafe(LineString.makePoints([p1, p2, p3, p1]))
  }

  private Geometry getGeometry(Point p1, Point p2)
  {
    v1 := Vector.makePoints(p1, p2)
    v2 := Vector.makePoints(Coord(0f, 0f), Coord(0f, 1f))
    Float angle := v1.angle(v2)

    trans := Transform2D().rotate(0f, 0f, angle + Float.pi / 2f).translate(p2.x, p2.y)
    transf := |Point p->Point|
    {
      Float[] cs := [p.x, p.y]
      trans.transform(cs)
      return Coord(cs[0], cs[1])
    }
    Geometry geom := geometry.val
    return geom.transform(transf)
  }

  override Void drawGeometry(Geometry geom, RenderEnv r)
  {
    if (geom is LineString)
    {
      LineString ls := geom
      drawLineSymbol(ls,r )
    }
    else if (geom is Polygon)
    {
      Polygon pg := geom
      drawLineSymbol(pg.shell, r)
      pg.holes.each |g|
      {
        drawLineSymbol(g, r)
      }
    }
    else if (geom is GeometryCollection)
    {
      GeometryCollection gs := geom
      gs.each |g|
      {
        drawGeometry(g, r)
      }
    }
  }

  private Void drawLineSymbol(LineString ls, RenderEnv r)
  {
    ls = ls.transform(r.view.world2Screen)
    g := r.g
    n := ls.size - 1
    for (i := 0; i < n; ++i)
    {
      Point p1 := ls.get(i)
      Point p2 := ls.get(i + 1)

      // out dis
      if (p1.distance2D(p2) < dis) continue

      LineString lsa := getGeometry(p1, p2)
      ps := toIntArray(lsa)

      if (g.brush != color) g.brush = color
      g.fillPolygon2(ps)
    }
  }

  private  static Array toIntArray(LineString ls)
  {
    ps := Array.allocate(ls.size * 2)
    i := 0
    ls.points.each |p|
    {
      ps.setInt(i++, p.x.toInt)
      ps.setInt(i++, p.y.toInt)
    }
    return ps
  }

}